/*
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *
 *  Authors:
 *  	Albert Marieges Garcia
 *  	Álex Pardo Fernández
 *  	Enric Mayas Márquez
 *  	Juan Carlos Calvo Tejedor
 *  	Marc Gironés Dezsényi
 *  
 *  Contact:
 *  	bcn.tours.android@gmail.com
 *  Webpage:
 *  	bcntours.co.cc
 *
 */
package com.BCNTours.Maps.Vista;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.BCNTours.R;
import com.BCNTours.AR.Utils.ARLocationManager;
import com.BCNTours.Maps.Utils.OverlayManager;
import com.BCNTours.Model.ApplicationData;
import com.BCNTours.Model.Attraction;
import com.BCNTours.Model.InformationPoint;
import com.BCNTours.Model.Monument;
import com.BCNTours.Model.Museum;
import com.BCNTours.Model.Poi;
import com.BCNTours.Vista.BCNTours;
import com.BCNTours.Vista.PoiDialog;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;


/**
 *	Class that displays a map centered at your current location, and draws your position and the position of surrounding points of interest.
 */
public class MapMode extends MapActivity {
	
	//Class attributes
	private List<Overlay> mapOverlays;
	private Drawable drawable;
	private OverlayManager itemizedOverlay;
	private OverlayManager myLocationOverlay = null;
	private Bundle extras;
	private Location myLocation;
	private static ApplicationData applicationData;
	private int tipo = 0;
	private Poi dialogPoi = null;
	private MapView mapView;
	private MapController mc;
	private GeoPoint center;
	private boolean firstCalled = true;
	private boolean networkOK = false;
	private Thread network;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        BCNTours.loading.dismiss();
        //Starts the wifi services
        ConnectivityManager cm = (ConnectivityManager) getApplicationContext().getSystemService( Context.CONNECTIVITY_SERVICE );
        if(cm.getActiveNetworkInfo() == null){
        
        	initializationWifi();
        }
        
        //Sets the map to display
        setContentView(R.layout.maps);
        
        //Loads the elements of the database that are needed by the class
        extras = getIntent().getExtras();
        applicationData = (ApplicationData) extras.get("com.ShowMe.Model.PoiList");
        
        mapView = (MapView) findViewById(R.id.mapview);
        mapView.setBuiltInZoomControls(true);
        
        mc = mapView.getController();
        setCenter(new GeoPoint(41387058,2170007));
        
        network = new Thread() {
    		ConnectivityManager cm = (ConnectivityManager) getApplicationContext().getSystemService( Context.CONNECTIVITY_SERVICE );
    		
    		@Override
    		public void run() {
    			super.run();
    			while(!networkOK){
    				if(cm.getActiveNetworkInfo()!=null){
    					networkOK = true;
//    					Toast.makeText(getApplicationContext(), "INTERNET OK", Toast.LENGTH_LONG).show();
    					mc.animateTo(center);
    				}
    			}
    			
    		}
    	};
        network.start();
        //Establishes where the map will be centered when created
        	//If gps location is available, it will center to the user's current location
        	//Else it will center to the default location
        
        if(isLocationAvailable()){
        	initializationLocation();
        }
        mapOverlays = mapView.getOverlays();
        drawable = this.getResources().getDrawable(R.drawable.marker);
        itemizedOverlay = new OverlayManager(drawable, this, true);
        createOverlays();
        
    }
    
    

    /**
     * Sets a new center for the map, and moves to it
     */
    protected void setCenter(GeoPoint newCenter){
    	center = newCenter;
        mc.setCenter(center);
        mc.setZoom(13);
    }
    
    /**
     * Loads the database points of interest and draw them on the map, according to the filter preferences.
     */
	protected void createOverlays(){
    	
    	GeoPoint point;
    	OverlayItem item;
    	//Point of interest related attributes
      	ArrayList<Attraction> listA;
      	ArrayList<Monument> listMo;
      	ArrayList<Museum> listMu;
      	ArrayList<InformationPoint> listI;
      	//Loads the filter preferences
      	boolean [] filterPreferences = applicationData.getFilterPreferences();
		@SuppressWarnings("rawtypes")
		Iterator i;
      	int pos;
      	String id;
      	double latitude;
      	double longitude;
      	String type;
      	
      	//Loads the needed database information
    	listA = applicationData.getAttractions();
    	listMo = applicationData.getMonuments();
    	listMu = applicationData.getMuseums();
    	listI = applicationData.getInformationPoints();
    	
    	//Adds attractions
    	if(filterPreferences[1]){
	    	i = listA.iterator();
	    	pos = 0;
	    	while(i.hasNext()){
	    		Attraction a = (Attraction) i.next();
	    		latitude = a.getGpsLat() * 1000000;
	    		longitude = a.getGpsLong() * 1000000;
	    		point = new GeoPoint((int)latitude,(int)longitude);
	    		id = Integer.toString(pos);
	    		type = "0";
	    		item = new OverlayItem(point, a.getName(), id + type);
	    		itemizedOverlay.addOverlay(item);
	    		pos ++;
	    	}
    	}	
	    	
    	//Adds monuments
    	if(filterPreferences[0]){
	    	i = listMo.iterator();
	    	pos = 0;
	    	while(i.hasNext()){
	    		Monument mo = (Monument) i.next();
	    		latitude = mo.getGpsLat() * 1000000;
	    		longitude = mo.getGpsLong() * 1000000;
	    		point = new GeoPoint((int)latitude,(int)longitude);
	    		id = Integer.toString(pos);
	    		type = "1";
	    		item = new OverlayItem(point, mo.getName(), id + type);
	    		itemizedOverlay.addOverlay(item);
	    		pos ++;
	    	}
    	}
    	
    	//Adds museums
    	if(filterPreferences[2]){
	    	i = listMu.iterator();
	    	pos = 0;
	    	while(i.hasNext()){
	    		Museum mu = (Museum) i.next();
	    		latitude = mu.getGpsLat() * 1000000;
	    		longitude = mu.getGpsLong() * 1000000;
	    		point = new GeoPoint((int)latitude,(int)longitude);
	    		id = Integer.toString(pos);
	    		type = "2";
	    		item = new OverlayItem(point, mu.getName(), id + type);
	    		itemizedOverlay.addOverlay(item);
	    		pos ++;
	    	}
    	}
    	
    	//Adds information points
    	if(filterPreferences[3]){
	    	i = listI.iterator();
	    	pos = 0;
	    	while(i.hasNext()){
	    		InformationPoint in = (InformationPoint) i.next();
	    		latitude = in.getGpsLat() * 1000000;
	    		longitude = in.getGpsLong() * 1000000;
	    		point = new GeoPoint((int)latitude,(int)longitude);
	    		id = Integer.toString(pos);
	    		type = "3";
	    		item = new OverlayItem(point, in.getName(), id + type);
	    		itemizedOverlay.addOverlay(item);
	    		pos ++;
	    	}
    	}
        
    	//Draws all the points
        mapOverlays.add(itemizedOverlay);
        itemizedOverlay.draw();
    }

	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}

	/**
	 * Triggers the dialog corresponding to a point of interest, which gives a number of options related to it.
	 * @param item
	 */
	public void showDialog(OverlayItem item){
		//Animates the map to the tapped information point
        mc.animateTo(item.getPoint()); 
		
        //Gets the type of the point of interest, and the position on that types list
   	    int info = Integer.parseInt(item.getSnippet());
   	    tipo = info%10;
   	    int positionPoi = info/10;
   	 
    	switch(tipo){
    	//Attractions
		case 0:
			dialogPoi = applicationData.getAttractions().get(positionPoi);
			break;
		//Monuments
		case 1:
			dialogPoi = applicationData.getMonuments().get(positionPoi);
			break;
		
		//Museums
		case 2:
			dialogPoi = applicationData.getMuseums().get(positionPoi);
			break;
    	//Information points
		case 3:
			dialogPoi = applicationData.getInformationPoints().get(positionPoi);
			break;
    	}
    	PoiDialog poiDialog = new PoiDialog(this, getApplicationContext(), dialogPoi);
    	poiDialog.show();
	}
	
	/**
	 * 	Checks whether the user has Internet connection or not, and in the latest case attempts to start it.
	 */
	private boolean initializationWifi(){
		final WifiManager wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
		//Checks if wifi connection is enabled
		if(!wifi.isWifiEnabled()){
			//Create a dialog asking whether to activate it or not
        	AlertDialog.Builder activateWifi = new AlertDialog.Builder(this);
        	activateWifi.setMessage(R.string.msgActivateWifi)
		       .setCancelable(false)
		       .setPositiveButton(R.string.msgYes, new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		        	   //Activates wifi connection
		        	   wifi.setWifiEnabled(true);
		        	   Toast.makeText(getApplicationContext(), R.string.msgSearchingWifi, Toast.LENGTH_LONG).show();   
		       		   dialog.cancel();
		       		
		           }
		       })
		       .setNegativeButton(R.string.msgNo, new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		        	    //Exits without any changes done, this will keep the map showing as a greyed layout, although all the markers will still
		        	   	//appear and will still be usable
		                dialog.cancel();
		                
		           }
		       });
		
			//Create and show the dialog
        	activateWifi.create();
        	activateWifi.show();
        	return false;
		}return true;
	}
	
	/**
     * Initialization the location
     */
    private void initializationLocation(){
	   
    	ARLocationManager myLocationManager = new ARLocationManager(getApplicationContext());
    	myLocationManager.requestUpdates(2000, 10, locationListener);
    	Location location = myLocationManager.getLastLocation();
    	myLocation = location;

    }
    
    /**
     * Location listener
     */
	private final LocationListener locationListener = new LocationListener() {
		//When change the location call the method which update the screen with the new dates 
		public void onLocationChanged(Location location) {
			if(firstCalled){	 
				//Creates the new center for the map, which is your current location
	        	center = new GeoPoint((int)(myLocation.getLatitude()*1000000),(int)(myLocation.getLongitude()*1000000));
	        	OverlayItem item = new OverlayItem(center, "", "");
	        	mapOverlays = mapView.getOverlays();
	            drawable = getApplication().getResources().getDrawable(R.drawable.marker_blue);
	            myLocationOverlay = new OverlayManager(drawable, MapMode.this, false);
	            myLocationOverlay.addOverlay(item);
	            mapOverlays.add(myLocationOverlay);
	        	myLocationOverlay.draw();
	        	mc.setCenter(center);
	        	mc.setZoom(13);
			}firstCalled = false;
		}
		//When position is not found
		public void onProviderDisabled(String provider){
			//Show an informative message
			Toast.makeText(getApplicationContext(), "No location found", Toast.LENGTH_LONG).show();
			finish();
		}
		public void onProviderEnabled(String provider){ }
		public void onStatusChanged(String provider, int status, Bundle extras){ }
	};
	
	/**
	 * Tells whether a location service is available or not.
	 */
	private boolean isLocationAvailable(){
		String context = Context.LOCATION_SERVICE;
		LocationManager locationManager = (LocationManager)getSystemService(context);
		Criteria criteria = new Criteria();
	    criteria.setAccuracy(Criteria.ACCURACY_FINE);
	    criteria.setAltitudeRequired(false);
	    criteria.setBearingRequired(false);
	    criteria.setCostAllowed(true);
	    criteria.setPowerRequirement(Criteria.POWER_LOW );
	    String provider = locationManager.getBestProvider(criteria, true);
	    
	    if (provider != null && locationManager.isProviderEnabled(provider)) {
            // Provider is enabled
            return true;
        } else {
        	
        	//Create the location dialog
        	AlertDialog.Builder builderRestore = new AlertDialog.Builder(this);
        	//Set the location of the dialog
        	builderRestore.setMessage(R.string.msgLocation)
		       .setCancelable(false)
		       .setPositiveButton(R.string.msgYes, new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		        	   Intent settingsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
		        	   startActivityForResult(settingsIntent,2);
		       		   dialog.cancel();
		       		
		           }
		       })
		       .setNegativeButton(R.string.msgNo, new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		                dialog.cancel();
		                
		           }
		       });
		
			//Create and show the dialog
			builderRestore.create();
			builderRestore.show();
        	
    		
        }
	    return false;
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// TODO Auto-generated method stub
		super.onActivityResult(requestCode, resultCode, data);
		if(requestCode == 2){
			if(isLocationAvailable()){
				//Starts the gps updates
				initializationLocation();
			}
		}
		else{
			Log.e("onActivityResult", "onActivityResult");
		}
	}

}